/*
 * Copyright 2000-2006 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jetbrains.idea.accurev.accurev;

import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.accurev.StreamGobbler;

import java.io.*;

public final class ExecResult {
  private int myExitCode = -1;
  private String myStdout = "";
  private String myStderr = "";
  private StreamGobbler myOutputGobbler;
  private StreamGobbler myErrorGobbler;
  private Throwable myException = null;
  private byte[] myByteOut;

  @SuppressWarnings({"HardCodedStringLiteral"})
  public String toString() {
    final StringBuffer buf = new StringBuffer();
    buf.append("ErrCode=");
    buf.append(getExitCode());
    buf.append("\nStdOut:------------\n");
    buf.append(getStdout());
    buf.append("\nStdErr:------------\n");
    buf.append(getStderr());
    if (getException() != null) {
      buf.append("\nException----------\n");
      buf.append(getException());
    }
    buf.append("\nEnd----------------\n");
    return buf.toString();
  }

  public int getExitCode() {
    return myExitCode;
  }

  public void setExitCode(final int exitCode) {
    myExitCode = exitCode;
  }

  public void setStdout(final String stdout) {
    myStdout = stdout;
  }

  public void setStderr(final String stderr) {
    myStderr = stderr;
  }

  public void setByteOut(final byte[] byteOut) {
    myByteOut = byteOut;
  }

  public InputStream getStdoutAsStream() {
    if (myOutputGobbler != null) {
      return myOutputGobbler.getResultAsStream();
    }
    return new ByteArrayInputStream(myStdout.getBytes());
  }

  @NotNull
  public String getStdout() {
    if (myOutputGobbler != null) {
      return readStreamConvertingLineSeparators(myOutputGobbler.getResultAsStream(), myOutputGobbler.getResultLength());
    }
    return myStdout;
  }

  public void setOutputGobbler(final StreamGobbler outputGobbler) {
    myOutputGobbler = outputGobbler;
  }

  public void setErrorGobbler(final StreamGobbler errorGobbler) {
    myErrorGobbler = errorGobbler;
  }

  @NotNull
  public String getStderr() {
    if (myErrorGobbler != null) {
      return readStreamConvertingLineSeparators(myErrorGobbler.getResultAsStream(), myErrorGobbler.getResultLength());
    }
    return myStderr;
  }

  public Throwable getException() {
    return myException;
  }

  public void setException(final Throwable exception) {
    myException = exception;
  }

  private static String readStreamConvertingLineSeparators(InputStream stream, int size) {
    BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
    try {
      StringBuffer result = new StringBuffer(size);
      do {
        String line = reader.readLine();
        if (line == null) break;
        result.append(line);
        result.append('\n');
      }
      while (true);
      return result.toString();
    }
    catch (IOException e) {
      throw new RuntimeException(e);
    }
    finally{
      try {
        reader.close();
      }
      catch (IOException e) {
        // Ignore
      }
    }
  }

  public byte[] getByteOut() {
    if (myOutputGobbler != null) {
      try {
        return FileUtil.loadBytes(myOutputGobbler.getResultAsStream(), myOutputGobbler.getResultLength());
      }
      catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
    return myByteOut;
  }
}
